/*
 * Licensed to the Tai Ping Jin Ke
 *
 * Copyright (c) 2022 .
 * All rights reserved.
 * 项目名称：太平金科-通用能力封装层-mybatis
 * 版权说明：本软件属太平金融科技服务(上海)有限公司所有，在未获得太平金融科技服务(上海)有限公司正式授权情况下，任何企业和个人，不能获取、阅读、安装、传播本软件涉及的任何受知识产权保护的内容。
 */
package com.taipingframework.mybatis.unid.tkmapper;

import com.taipingframework.utility.unid.AppGenKey;
import org.springframework.lang.NonNull;
import tk.mybatis.mapper.genid.GenId;

/**
 * tk.mapper 分布式全局唯一ID生成策略
 * <p>
 * (1)分布式全局ID设计考量：
 * 服务器标识 + 当前线程标识 + 时间戳 + 计数器
 * (2)令人悲伤的事：tk.mapper本身的MySqlMapper支持批量插入，例如：MySqlMapper.insertList(recordList)。
 * 但是，经过实际测试验证得知：@KeySql(genId = AppGenId.class)这种方式在执行批量插入操作时，无法触发GenId机制！
 * 因此，对于单条插入，这种方式还是很方便的，因为不需要每次都显式触发生成全局唯一ID的执行。。。
 * (3)针对(2)的问题，设计者不可能注意不到，因此，tk.mapper还有另外一个不支持主键策略的批量插入接口tk.mybatis.mapper.additional.insert.InsertListMapper《T》，
 * 幸运的是，该接口自2018-04-22 后已经支持 @KeySql 注解的 genId 方式。我们在引用时，需要区别于MySqlMapper下支持主键策略的接口tk.mybatis.mapper.common.special.InsertListMapper《T》
 */
public final class AppGenId implements GenId<String> {

    private static AppGenKey genKey;

    @Override
    public String genId(String table, String column) {
        return String.valueOf(AppGenId.genKey.getUniqueKey());
    }

    /**
     * 设置 创建分布式全局ID 的对象
     */
    public void setGenKey(@NonNull AppGenKey genKey) {
        AppGenId.setSyncGenKey(genKey);
    }

    private static synchronized void setSyncGenKey(AppGenKey genKey) {
        AppGenId.genKey = genKey;
    }
}
/*
 * 假如你在使用 tk.mapper 这个ORM框架，那么在数据对象主键字段上可以通过注解 @KeySql 引入自定义的全局唯一ID生成策略
 *
 * @Id
 * @Column(name = "product_id")
 * // --- 这里区别一下mysql与oracle
 * //mysql主键自增：
 * //（1）@GeneratedValue(strategy=GenerationType.IDENTITY) --->> auto_increment
 * //（2）@GeneratedValue(strategy = GenerationType.IDENTITY, generator = "select upper(replace(uuid(),'-',''))") --->>使用uuid
 * //（3）@KeySql(useGeneratedKeys = true) 或者 @GeneratedValue(generator = "JDBC")
 * //（4）@KeySql(sql = "select upper(replace(uuid(),'-',''))", order = ORDER.AFTER)
 * //oracle主键自增：
 * //（1）@GeneratedValue(strategy = GenerationType.IDENTITY, generator = "select sequence.nextval from dual")
 * //（2）@KeySql(sql = "SELECT SEQUENCE_TOP_ID.NEXTVAL FROM DUAL", order = ORDER.BEFORE)
 * //（3）@KeySql(sql = "SELECT SYS_GUID() FROM DUAL", order = ORDER.BEFORE)
 * @KeySql(genId = AppGenId.class)
 * private Integer productId;
 *
 */
